package _general.geometry;

/**
 * objekte dieser Klasse sind immutable
 * @author acid
 *
 */
public class Edge {
	
	final Node start;
	final Node end;
	
	public Edge(Node p1, Node p2) {
		super();
		
		this.start = p1;
		this.end = p2;
		
		if (start.getX() >= end.getX()) {
			throw new IllegalArgumentException("the position of the startnode is more right than the position of the endnode!!");
		}
	}
	
	
	public Node getStart() {
		return start;
	}

	public Node getEnd() {
		return end;
	}
	
	public boolean isIntersection(Edge edge1) {
		
//		 System.out.println(getDeterminant(edge1.getStart(), edge1.getEnd(), edge2.getStart()));
//		 System.out.println(getDeterminant(edge1.getStart(), edge1.getEnd(), edge2.getEnd()));
//		 System.out.println(getDeterminant(edge2.getStart(), edge2.getEnd(), edge1.getStart()));
//		 System.out.println(getDeterminant(edge2.getStart(), edge2.getEnd(), edge1.getEnd()));
		
		return ((getDeterminant(this.getStart(), this.getEnd(), edge1.getStart()) * 
				getDeterminant(this.getStart(), this.getEnd(), edge1.getEnd())) < 0 &&
				(getDeterminant(edge1.getStart(), edge1.getEnd(), this.getStart()) * 
				getDeterminant(edge1.getStart(), edge1.getEnd(), this.getEnd())) < 0);
	}
	
	
	public Cross getIntersection(Edge edge1) {

		Node edge2DirectionVector = new Node (
				edge1.getEnd().getX() - edge1.getStart().getX(),
				edge1.getEnd().getY() - edge1.getStart().getY());
		
		double[][] linearSystem = new double[][] {
				{this.getEnd().getX() - this.getStart().getX(), this.getEnd().getY() - this.getStart().getY()},
				{edge1.getEnd().getX() - edge1.getStart().getX(), edge1.getEnd().getY() - edge1.getStart().getY()},
				{edge1.getStart().getX() - this.getStart().getX(), edge1.getStart().getY() - this.getStart().getY()}}; 
		
		double pivot = (linearSystem[0][1] / linearSystem[0][0]);
		
		linearSystem[0][1] = 0;
		linearSystem[1][1] -= linearSystem[1][0] * pivot;
		linearSystem[2][1] -= linearSystem[2][0] * pivot;
		
		double epsilon = Math.abs(linearSystem[2][1] / linearSystem[1][1]);
		
		//System.out.println("epsilon: " + epsilon);
		//System.out.println("Intersection at point (" + (edge2.getStart().getX() + (epsilon * edge2DirectionVector.getX())) + ", " + (edge2.getStart().getY() + epsilon * edge2DirectionVector.getY()) + ")");
		
		return new Cross(
				(edge1.getStart().getX() + epsilon * edge2DirectionVector.getX()), 
				(edge1.getStart().getY() + epsilon * edge2DirectionVector.getY()), 
				this, 
				edge1);
	}
	
	private double getDeterminant(Point p1, Point p2, Point p3) {
		/*
		 * | p1.getX()	p1.getY()	1 |
		 * | p2.getX()	p2.getY()	1 |
		 * | p3.getX()	p3.getY()	1 |
		 */
		double det = p1.getX() * p2.getY() + 
			  		p1.getY() * p3.getX() + 
			  		p2.getX() * p3.getY() -
			  		p2.getY() * p3.getX() -
			  		p1.getX() * p3.getY() -
			  		p1.getY() * p2.getX();
		
		return det;
	}

}
